﻿// Type: System.Numerics.Complex
// Assembly: System.Numerics, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
// MVID: 2BCD559E-1E00-4581-80D1-080BCD16D4B6
// Assembly location: C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.Numerics.dll

using System.Globalization;

// ReSharper disable once CheckNamespace
// ReSharper disable CompareOfFloatsByEqualityOperator

namespace System.Numerics
{
    /// <summary>
    ///     Represents a complex number.
    /// </summary>
    public struct Complex : IEquatable<Complex>, IFormattable
    {
        /// <summary>
        ///     Returns a new <see cref="T:System.Numerics.Complex" /> instance with a real number equal to zero and an imaginary
        ///     number equal to zero.
        /// </summary>
        public static readonly Complex Zero = new Complex(0.0, 0.0);

        /// <summary>
        ///     Returns a new <see cref="T:System.Numerics.Complex" /> instance with a real number equal to one and an imaginary
        ///     number equal to zero.
        /// </summary>
        public static readonly Complex One = new Complex(1.0, 0.0);

        /// <summary>
        ///     Returns a new <see cref="T:System.Numerics.Complex" /> instance with a real number equal to zero and an imaginary
        ///     number equal to one.
        /// </summary>
        public static readonly Complex ImaginaryOne = new Complex(0.0, 1.0);

        private readonly double _imaginary;
        private readonly double _real;

        static Complex()
        {
        }

        /// <summary>
        ///     Initializes a new instance of the <see cref="T:System.Numerics.Complex" /> structure using the specified real and
        ///     imaginary values.
        /// </summary>
        /// <param name="real">The real part of the complex number.</param>
        /// <param name="imaginary">The imaginary part of the complex number.</param>
        public Complex(double real, double imaginary)
        {
            _real = real;
            _imaginary = imaginary;
        }

        //private const double LOG_10_INV = 0.43429448190325;

        /// <summary>
        ///     Gets the real component of the current <see cref="T:System.Numerics.Complex" /> object.
        /// </summary>
        /// <returns>
        ///     The real component of a complex number.
        /// </returns>
        public double Real
        {
            get { return _real; }
        }

        /// <summary>
        ///     Gets the imaginary component of the current <see cref="T:System.Numerics.Complex" /> object.
        /// </summary>
        /// <returns>
        ///     The imaginary component of a complex number.
        /// </returns>
        public double Imaginary
        {
            get { return _imaginary; }
        }

        /// <summary>
        ///     Gets the magnitude (or absolute value) of a complex number.
        /// </summary>
        /// <returns>
        ///     The magnitude of the current instance.
        /// </returns>
        public double Magnitude
        {
            get { return Abs(this); }
        }

        /// <summary>
        ///     Gets the phase of a complex number.
        /// </summary>
        /// <returns>
        ///     The phase of a complex number, in radians.
        /// </returns>
        public double Phase
        {
            get { return Math.Atan2(_imaginary, _real); }
        }

        /// <summary>
        ///     Returns a value that indicates whether the current instance and a specified complex number have the same value.
        /// </summary>
        /// <returns>
        ///     true if this complex number and <paramref name="value" /> have the same value; otherwise, false.
        /// </returns>
        /// <param name="value">The complex number to compare.</param>
        public bool Equals(Complex value)
        {
            if (_real.Equals(value._real))
                return _imaginary.Equals(value._imaginary);
            return false;
        }

        /// <summary>
        ///     Converts the value of the current complex number to its equivalent string representation in Cartesian form by using
        ///     the specified format and culture-specific format information for its real and imaginary parts.
        /// </summary>
        /// <returns>
        ///     The string representation of the current instance in Cartesian form, as specified by <paramref name="format" /> and
        ///     <paramref name="provider" />.
        /// </returns>
        /// <param name="format">A standard or custom numeric format string.</param>
        /// <param name="provider">An object that supplies culture-specific formatting information.</param>
        /// <exception cref="T:System.FormatException"><paramref name="format" /> is not a valid format string.</exception>
        public string ToString(string format, IFormatProvider provider)
        {
            return string.Format(provider, "({0}, {1})", new object[]
            {
                _real.ToString(format, provider),
                _imaginary.ToString(format, provider)
            });
        }

        /// <summary>
        ///     Defines an implicit conversion of a 16-bit signed integer to a complex number.
        /// </summary>
        /// <returns>
        ///     An object that contains the value of the <paramref name="value" /> parameter as its real part and zero as its
        ///     imaginary part.
        /// </returns>
        /// <param name="value">The value to convert to a complex number.</param>
        public static implicit operator Complex(short value)
        {
            return new Complex(value, 0.0);
        }

        /// <summary>
        ///     Defines an implicit conversion of a 32-bit signed integer to a complex number.
        /// </summary>
        /// <returns>
        ///     An object that contains the value of the <paramref name="value" /> parameter as its real part and zero as its
        ///     imaginary part.
        /// </returns>
        /// <param name="value">The value to convert to a complex number.</param>
        public static implicit operator Complex(int value)
        {
            return new Complex(value, 0.0);
        }

        /// <summary>
        ///     Defines an implicit conversion of a 64-bit signed integer to a complex number.
        /// </summary>
        /// <returns>
        ///     An object that contains the value of the <paramref name="value" /> parameter as its real part and zero as its
        ///     imaginary part.
        /// </returns>
        /// <param name="value">The value to convert to a complex number.</param>
        public static implicit operator Complex(long value)
        {
            return new Complex(value, 0.0);
        }

        /// <summary>
        ///     Defines an implicit conversion of a 16-bit unsigned integer to a complex number.
        /// </summary>
        /// <returns>
        ///     An object that contains the value of the <paramref name="value" /> parameter as its real part and zero as its
        ///     imaginary part.
        /// </returns>
        /// <param name="value">The value to convert to a complex number.</param>
        [CLSCompliant(false)]
        public static implicit operator Complex(ushort value)
        {
            return new Complex(value, 0.0);
        }

        /// <summary>
        ///     Defines an implicit conversion of a 32-bit unsigned integer to a complex number.
        /// </summary>
        /// <returns>
        ///     An object that contains the value of the <paramref name="value" /> parameter as its real part and zero as its
        ///     imaginary part.
        /// </returns>
        /// <param name="value">The value to convert to a complex number.</param>
        [CLSCompliant(false)]
        public static implicit operator Complex(uint value)
        {
            return new Complex(value, 0.0);
        }

        /// <summary>
        ///     Defines an implicit conversion of a 64-bit unsigned integer to a complex number.
        /// </summary>
        /// <returns>
        ///     An object that contains the value of the <paramref name="value" /> parameter as its real part and zero as its
        ///     imaginary part.
        /// </returns>
        /// <param name="value">The value to convert to a complex number.</param>
        [CLSCompliant(false)]
        public static implicit operator Complex(ulong value)
        {
            return new Complex(value, 0.0);
        }

        /// <summary>
        ///     Defines an implicit conversion of a signed byte to a complex number.
        /// </summary>
        /// <returns>
        ///     An object that contains the value of the <paramref name="value" /> parameter as its real part and zero as its
        ///     imaginary part.
        /// </returns>
        /// <param name="value">The value to convert to a complex number.</param>
        [CLSCompliant(false)]
        public static implicit operator Complex(sbyte value)
        {
            return new Complex(value, 0.0);
        }

        /// <summary>
        ///     Defines an implicit conversion of an unsigned byte to a complex number.
        /// </summary>
        /// <returns>
        ///     An object that contains the value of the <paramref name="value" /> parameter as its real part and zero as its
        ///     imaginary part.
        /// </returns>
        /// <param name="value">The value to convert to a complex number.</param>
        public static implicit operator Complex(byte value)
        {
            return new Complex(value, 0.0);
        }

        /// <summary>
        ///     Defines an implicit conversion of a single-precision floating-point number to a complex number.
        /// </summary>
        /// <returns>
        ///     An object that contains the value of the <paramref name="value" /> parameter as its real part and zero as its
        ///     imaginary part.
        /// </returns>
        /// <param name="value">The value to convert to a complex number.</param>
        public static implicit operator Complex(float value)
        {
            return new Complex(value, 0.0);
        }

        /// <summary>
        ///     Defines an implicit conversion of a double-precision floating-point number to a complex number.
        /// </summary>
        /// <returns>
        ///     An object that contains the value of the <paramref name="value" /> parameter as its real part and zero as its
        ///     imaginary part.
        /// </returns>
        /// <param name="value">The value to convert to a complex number.</param>
        public static implicit operator Complex(double value)
        {
            return new Complex(value, 0.0);
        }

        //public static explicit operator Complex(BigInteger value)
        //{
        //    return new Complex((double)value, 0.0);
        //}
        /// <summary>
        ///     Defines an explicit conversion of a <see cref="T:System.Numerics.BigInteger" /> value to a complex number.
        /// </summary>
        /// <returns>
        ///     A complex number that has a real component equal to <paramref name="value" /> and an imaginary component equal to
        ///     zero.
        /// </returns>
        /// <param name="value">The value to convert to a complex number.</param>
        /// <summary>
        ///     Defines an explicit conversion of a <see cref="T:System.Decimal" /> value to a complex number.
        /// </summary>
        /// <returns>
        ///     A complex number that has a real component equal to <paramref name="value" /> and an imaginary component equal to
        ///     zero.
        /// </returns>
        /// <param name="value">The value to convert to a complex number.</param>
        public static explicit operator Complex(Decimal value)
        {
            return new Complex((double) value, 0.0);
        }

        /// <summary>
        ///     Returns the additive inverse of a specified complex number.
        /// </summary>
        /// <returns>
        ///     The result of the <see cref="P:System.Numerics.Complex.Real" /> and
        ///     <see cref="P:System.Numerics.Complex.Imaginary" /> components of the <paramref name="value" /> parameter multiplied
        ///     by -1.
        /// </returns>
        /// <param name="value">The value to negate.</param>
        public static Complex operator -(Complex value)
        {
            return new Complex(-value._real, -value._imaginary);
        }

        /// <summary>
        ///     Adds two complex numbers.
        /// </summary>
        /// <returns>
        ///     The sum of <paramref name="left" /> and <paramref name="right" />.
        /// </returns>
        /// <param name="left">The first value to add.</param>
        /// <param name="right">The second value to add.</param>
        public static Complex operator +(Complex left, Complex right)
        {
            return new Complex(left._real + right._real, left._imaginary + right._imaginary);
        }

        /// <summary>
        ///     Subtracts a complex number from another complex number.
        /// </summary>
        /// <returns>
        ///     The result of subtracting <paramref name="right" /> from <paramref name="left" />.
        /// </returns>
        /// <param name="left">The value to subtract from (the minuend).</param>
        /// <param name="right">The value to subtract (the subtrahend).</param>
        public static Complex operator -(Complex left, Complex right)
        {
            return new Complex(left._real - right._real, left._imaginary - right._imaginary);
        }

        /// <summary>
        ///     Multiplies two specified complex numbers.
        /// </summary>
        /// <returns>
        ///     The product of <paramref name="left" /> and <paramref name="right" />.
        /// </returns>
        /// <param name="left">The first value to multiply.</param>
        /// <param name="right">The second value to multiply.</param>
        public static Complex operator *(Complex left, Complex right)
        {
            return new Complex(left._real*right._real - left._imaginary*right._imaginary,
                left._imaginary*right._real + left._real*right._imaginary);
        }

        /// <summary>
        ///     Divides a specified complex number by another specified complex number.
        /// </summary>
        /// <returns>
        ///     The result of dividing <paramref name="left" /> by <paramref name="right" />.
        /// </returns>
        /// <param name="left">The value to be divided.</param>
        /// <param name="right">The value to divide by.</param>
        public static Complex operator /(Complex left, Complex right)
        {
            double num1 = left._real;
            double num2 = left._imaginary;
            double num3 = right._real;
            double num4 = right._imaginary;
            if (Math.Abs(num4) < Math.Abs(num3))
            {
                double num5 = num4/num3;
                return new Complex((num1 + num2*num5)/(num3 + num4*num5), (num2 - num1*num5)/(num3 + num4*num5));
            }
            else
            {
                double num5 = num3/num4;
                return new Complex((num2 + num1*num5)/(num4 + num3*num5), (-num1 + num2*num5)/(num4 + num3*num5));
            }
        }

        /// <summary>
        ///     Returns a value that indicates whether two complex numbers are equal.
        /// </summary>
        /// <returns>
        ///     true if the <paramref name="left" /> and <paramref name="right" /> parameters have the same value; otherwise,
        ///     false.
        /// </returns>
        /// <param name="left">The first complex number to compare.</param>
        /// <param name="right">The second complex number to compare.</param>
        public static bool operator ==(Complex left, Complex right)
        {
            return left._real == right._real && left._imaginary == right._imaginary;
        }

        /// <summary>
        ///     Returns a value that indicates whether two complex numbers are not equal.
        /// </summary>
        /// <returns>
        ///     true if <paramref name="left" /> and <paramref name="right" /> are not equal; otherwise, false.
        /// </returns>
        /// <param name="left">The first value to compare.</param>
        /// <param name="right">The second value to compare.</param>
        public static bool operator !=(Complex left, Complex right)
        {
            if (left._real == right._real)
                return left._imaginary != right._imaginary;
            return true;
        }

        /// <summary>
        ///     Creates a complex number from a point's polar coordinates.
        /// </summary>
        /// <returns>
        ///     A complex number.
        /// </returns>
        /// <param name="magnitude">
        ///     The magnitude, which is the distance from the origin (the intersection of the x-axis and the
        ///     y-axis) to the number.
        /// </param>
        /// <param name="phase">The phase, which is the angle from the line to the horizontal axis, measured in radians.</param>
        public static Complex FromPolarCoordinates(double magnitude, double phase)
        {
            return new Complex(magnitude*Math.Cos(phase), magnitude*Math.Sin(phase));
        }

        /// <summary>
        ///     Returns the additive inverse of a specified complex number.
        /// </summary>
        /// <returns>
        ///     The result of the <see cref="P:System.Numerics.Complex.Real" /> and
        ///     <see cref="P:System.Numerics.Complex.Imaginary" /> components of the <paramref name="value" /> parameter multiplied
        ///     by -1.
        /// </returns>
        /// <param name="value">A complex number.</param>
        public static Complex Negate(Complex value)
        {
            return -value;
        }

        /// <summary>
        ///     Adds two complex numbers and returns the result.
        /// </summary>
        /// <returns>
        ///     The sum of <paramref name="left" /> and <paramref name="right" />.
        /// </returns>
        /// <param name="left">The first complex number to add.</param>
        /// <param name="right">The second complex number to add.</param>
        public static Complex Add(Complex left, Complex right)
        {
            return left + right;
        }

        /// <summary>
        ///     Subtracts one complex number from another and returns the result.
        /// </summary>
        /// <returns>
        ///     The result of subtracting <paramref name="right" /> from <paramref name="left" />.
        /// </returns>
        /// <param name="left">The value to subtract from (the minuend).</param>
        /// <param name="right">The value to subtract (the subtrahend).</param>
        public static Complex Subtract(Complex left, Complex right)
        {
            return left - right;
        }

        /// <summary>
        ///     Returns the product of two complex numbers.
        /// </summary>
        /// <returns>
        ///     The product of the <paramref name="left" /> and <paramref name="right" /> parameters.
        /// </returns>
        /// <param name="left">The first complex number to multiply.</param>
        /// <param name="right">The second complex number to multiply.</param>
        public static Complex Multiply(Complex left, Complex right)
        {
            return left*right;
        }

        /// <summary>
        ///     Divides one complex number by another and returns the result.
        /// </summary>
        /// <returns>
        ///     The quotient of the division.
        /// </returns>
        /// <param name="dividend">The complex number to be divided.</param>
        /// <param name="divisor">The complex number to divide by.</param>
        public static Complex Divide(Complex dividend, Complex divisor)
        {
            return dividend/divisor;
        }

        /// <summary>
        ///     Gets the absolute value (or magnitude) of a complex number.
        /// </summary>
        /// <returns>
        ///     The absolute value of <paramref name="value" />.
        /// </returns>
        /// <param name="value">A complex number.</param>
        public static double Abs(Complex value)
        {
            if (double.IsInfinity(value._real) || double.IsInfinity(value._imaginary))
                return double.PositiveInfinity;
            double num1 = Math.Abs(value._real);
            double num2 = Math.Abs(value._imaginary);
            if (num1 > num2)
            {
                double num3 = num2/num1;
                return num1*Math.Sqrt(1.0 + num3*num3);
            }
            else
            {
                if (num2 == 0.0)
                    return num1;
                double num3 = num1/num2;
                return num2*Math.Sqrt(1.0 + num3*num3);
            }
        }

        /// <summary>
        ///     Computes the conjugate of a complex number and returns the result.
        /// </summary>
        /// <returns>
        ///     The conjugate of <paramref name="value" />.
        /// </returns>
        /// <param name="value">A complex number.</param>
        public static Complex Conjugate(Complex value)
        {
            return new Complex(value._real, -value._imaginary);
        }

        /// <summary>
        ///     Returns the multiplicative inverse of a complex number.
        /// </summary>
        /// <returns>
        ///     The reciprocal of <paramref name="value" />.
        /// </returns>
        /// <param name="value">A complex number.</param>
        public static Complex Reciprocal(Complex value)
        {
            return value._real == 0.0 && value._imaginary == 0.0 ? Zero : One/value;
        }

        /// <summary>
        ///     Returns a value that indicates whether the current instance and a specified object have the same value.
        /// </summary>
        /// <returns>
        ///     true if the <paramref name="obj" /> parameter is a <see cref="T:System.Numerics.Complex" /> object or a type
        ///     capable of implicit conversion to a <see cref="T:System.Numerics.Complex" /> object, and its value is equal to the
        ///     current <see cref="T:System.Numerics.Complex" /> object; otherwise, false.
        /// </returns>
        /// <param name="obj">The object to compare.</param>
        public override bool Equals(object obj)
        {
            if (!(obj is Complex))
                return false;
            return this == (Complex) obj;
        }

        /// <summary>
        ///     Converts the value of the current complex number to its equivalent string representation in Cartesian form.
        /// </summary>
        /// <returns>
        ///     The string representation of the current instance in Cartesian form.
        /// </returns>
        public override string ToString()
        {
            return string.Format(CultureInfo.CurrentCulture, "({0}, {1})", new object[]
            {
                _real,
                _imaginary
            });
        }

        /// <summary>
        ///     Converts the value of the current complex number to its equivalent string representation in Cartesian form by using
        ///     the specified format for its real and imaginary parts.
        /// </summary>
        /// <returns>
        ///     The string representation of the current instance in Cartesian form.
        /// </returns>
        /// <param name="format">A standard or custom numeric format string.</param>
        /// <exception cref="T:System.FormatException"><paramref name="format" /> is not a valid format string.</exception>
        public string ToString(string format)
        {
            return string.Format(CultureInfo.CurrentCulture, "({0}, {1})", new object[]
            {
                _real.ToString(format, CultureInfo.CurrentCulture),
                _imaginary.ToString(format, CultureInfo.CurrentCulture)
            });
        }

        /// <summary>
        ///     Converts the value of the current complex number to its equivalent string representation in Cartesian form by using
        ///     the specified culture-specific formatting information.
        /// </summary>
        /// <returns>
        ///     The string representation of the current instance in Cartesian form, as specified by <paramref name="provider" />.
        /// </returns>
        /// <param name="provider">An object that supplies culture-specific formatting information.</param>
        public string ToString(IFormatProvider provider)
        {
            return string.Format(provider, "({0}, {1})", new object[]
            {
                _real,
                _imaginary
            });
        }

        /// <summary>
        ///     Returns the hash code for the current <see cref="T:System.Numerics.Complex" /> object.
        /// </summary>
        /// <returns>
        ///     A 32-bit signed integer hash code.
        /// </returns>
        public override int GetHashCode()
        {
            return _real.GetHashCode()%99999997 ^ _imaginary.GetHashCode();
        }

        /// <summary>
        ///     Returns the sine of the specified complex number.
        /// </summary>
        /// <returns>
        ///     The sine of <paramref name="value" />.
        /// </returns>
        /// <param name="value">A complex number.</param>
        public static Complex Sin(Complex value)
        {
            double num1 = value._real;
            double num2 = value._imaginary;
            return new Complex(Math.Sin(num1)*Math.Cosh(num2), Math.Cos(num1)*Math.Sinh(num2));
        }

        /// <summary>
        ///     Returns the hyperbolic sine of the specified complex number.
        /// </summary>
        /// <returns>
        ///     The hyperbolic sine of <paramref name="value" />.
        /// </returns>
        /// <param name="value">A complex number.</param>
        public static Complex Sinh(Complex value)
        {
            double num1 = value._real;
            double num2 = value._imaginary;
            return new Complex(Math.Sinh(num1)*Math.Cos(num2), Math.Cosh(num1)*Math.Sin(num2));
        }

        /// <summary>
        ///     Returns the angle that is the arc sine of the specified complex number.
        /// </summary>
        /// <returns>
        ///     The angle which is the arc sine of <paramref name="value" />.
        /// </returns>
        /// <param name="value">A complex number.</param>
        public static Complex Asin(Complex value)
        {
            return -ImaginaryOne*Log(ImaginaryOne*value + Sqrt(One - value*value));
        }

        /// <summary>
        ///     Returns the cosine of the specified complex number.
        /// </summary>
        /// <returns>
        ///     The cosine of <paramref name="value" />.
        /// </returns>
        /// <param name="value">A complex number.</param>
        public static Complex Cos(Complex value)
        {
            double num1 = value._real;
            double num2 = value._imaginary;
            return new Complex(Math.Cos(num1)*Math.Cosh(num2), -(Math.Sin(num1)*Math.Sinh(num2)));
        }

        /// <summary>
        ///     Returns the hyperbolic cosine of the specified complex number.
        /// </summary>
        /// <returns>
        ///     The hyperbolic cosine of <paramref name="value" />.
        /// </returns>
        /// <param name="value">A complex number.</param>
        public static Complex Cosh(Complex value)
        {
            double num1 = value._real;
            double num2 = value._imaginary;
            return new Complex(Math.Cosh(num1)*Math.Cos(num2), Math.Sinh(num1)*Math.Sin(num2));
        }

        /// <summary>
        ///     Returns the angle that is the arc cosine of the specified complex number.
        /// </summary>
        /// <returns>
        ///     The angle, measured in radians, which is the arc cosine of <paramref name="value" />.
        /// </returns>
        /// <param name="value">A complex number that represents a cosine.</param>
        public static Complex Acos(Complex value)
        {
            return -ImaginaryOne*Log(value + ImaginaryOne*Sqrt(One - value*value));
        }

        /// <summary>
        ///     Returns the tangent of the specified complex number.
        /// </summary>
        /// <returns>
        ///     The tangent of <paramref name="value" />.
        /// </returns>
        /// <param name="value">A complex number.</param>
        public static Complex Tan(Complex value)
        {
            return Sin(value)/Cos(value);
        }

        /// <summary>
        ///     Returns the hyperbolic tangent of the specified complex number.
        /// </summary>
        /// <returns>
        ///     The hyperbolic tangent of <paramref name="value" />.
        /// </returns>
        /// <param name="value">A complex number.</param>
        public static Complex Tanh(Complex value)
        {
            return Sinh(value)/Cosh(value);
        }

        /// <summary>
        ///     Returns the angle that is the arc tangent of the specified complex number.
        /// </summary>
        /// <returns>
        ///     The angle that is the arc tangent of <paramref name="value" />.
        /// </returns>
        /// <param name="value">A complex number.</param>
        public static Complex Atan(Complex value)
        {
            var complex = new Complex(2.0, 0.0);
            return ImaginaryOne/complex*(Log(One - ImaginaryOne*value) - Log(One + ImaginaryOne*value));
        }

        /// <summary>
        ///     Returns the natural (base e) logarithm of a specified complex number.
        /// </summary>
        /// <returns>
        ///     The natural (base e) logarithm of <paramref name="value" />.
        /// </returns>
        /// <param name="value">A complex number.</param>
        public static Complex Log(Complex value)
        {
            return new Complex(Math.Log(Abs(value)), Math.Atan2(value._imaginary, value._real));
        }

        /// <summary>
        ///     Returns the logarithm of a specified complex number in a specified base.
        /// </summary>
        /// <returns>
        ///     The logarithm of <paramref name="value" /> in base <paramref name="baseValue" />.
        /// </returns>
        /// <param name="value">A complex number.</param>
        /// <param name="baseValue">The base of the logarithm.</param>
        public static Complex Log(Complex value, double baseValue)
        {
            return Log(value)/Log(baseValue);
        }

        /// <summary>
        ///     Returns the base-10 logarithm of a specified complex number.
        /// </summary>
        /// <returns>
        ///     The base-10 logarithm of <paramref name="value" />.
        /// </returns>
        /// <param name="value">A complex number.</param>
        public static Complex Log10(Complex value)
        {
            return Scale(Log(value), 0.43429448190325);
        }

        /// <summary>
        ///     Returns e raised to the power specified by a complex number.
        /// </summary>
        /// <returns>
        ///     The number e raised to the power <paramref name="value" />.
        /// </returns>
        /// <param name="value">A complex number that specifies a power.</param>
        public static Complex Exp(Complex value)
        {
            double num = Math.Exp(value._real);
            return new Complex(num*Math.Cos(value._imaginary), num*Math.Sin(value._imaginary));
        }

        /// <summary>
        ///     Returns the square root of a specified complex number.
        /// </summary>
        /// <returns>
        ///     The square root of <paramref name="value" />.
        /// </returns>
        /// <param name="value">A complex number.</param>
        public static Complex Sqrt(Complex value)
        {
            return FromPolarCoordinates(Math.Sqrt(value.Magnitude), value.Phase/2.0);
        }

        /// <summary>
        ///     Returns a specified complex number raised to a power specified by a complex number.
        /// </summary>
        /// <returns>
        ///     The complex number <paramref name="value" /> raised to the power <paramref name="power" />.
        /// </returns>
        /// <param name="value">A complex number to be raised to a power.</param>
        /// <param name="power">A complex number that specifies a power.</param>
        public static Complex Pow(Complex value, Complex power)
        {
            if (power == Zero)
                return One;
            if (value == Zero)
                return Zero;
            double x = value._real;
            double y1 = value._imaginary;
            double y2 = power._real;
            double num1 = power._imaginary;
            double num2 = Abs(value);
            double num3 = Math.Atan2(y1, x);
            double num4 = y2*num3 + num1*Math.Log(num2);
            double num5 = Math.Pow(num2, y2)*Math.Pow(Math.E, -num1*num3);
            return new Complex(num5*Math.Cos(num4), num5*Math.Sin(num4));
        }

        /// <summary>
        ///     Returns a specified complex number raised to a power specified by a double-precision floating-point number.
        /// </summary>
        /// <returns>
        ///     The complex number <paramref name="value" /> raised to the power <paramref name="power" />.
        /// </returns>
        /// <param name="value">A complex number to be raised to a power.</param>
        /// <param name="power">A double-precision floating-point number that specifies a power.</param>
        public static Complex Pow(Complex value, double power)
        {
            return Pow(value, new Complex(power, 0.0));
        }

        private static Complex Scale(Complex value, double factor)
        {
            return new Complex(factor*value._real, factor*value._imaginary);
        }
    }
}